<meta args="Main"/>
<div class="topbar">
    <div s="window" s-window="{href:Main.topbarLeftUrl}" class="pull-left"></div>
    <div class="pull-right topbar-right">
        <div s="window" s-window="{href:Main.topbarRightUrl}"></div>
    </div>
</div>
<div class="main-view" id="mainView">
    <div class="main-left-sidebar">
        <div class="sidebar-fold"></div>
        <div id="menuPanel" s="tpl" class="sidebar-menu-panel">
            {% $.each(this.menus, function(i, menu){ %}
            <div class="sidebar-nav {%if(this.open === false){out.print('menu-close');}%}">
                {%if(menu.children && menu.children.length){%}
                <div class="sidebar-title">
                    <div class="sidebar-title-inner"><span
                            class="sidebar-title-icon {%=menu.icon%}"></span>
                        <span class="sidebar-title-text">{%=menu.title%}</span>
                    <span class="sidebar-manage">
                        <i class="caret"></i>
                    </span>
                    </div>
                </div>
                <ul class="s-ui-trans">
                    {% $.each(this.children || {}, function(i, c){ %}
                    <li class="nav-item " menuUrl="{%=c.url%}" menuId="{%=c.id%}"
                        s-click="openMenuById('{%=c.id%}')">
                        <a class="s-ui-trans" href="javascript:;">
                            <div class="nav-icon s-ui-trans"><i class="{%=c.icon || 'fa fa-file-text-o' %}"></i>
                            </div>
                            <span class="nav-title ng-binding">{%=c.title%}</span>
                        </a>
                    </li>
                    {% }) %}
                </ul>
                {%} else {%}
                <div class="sidebar-title" menuUrl="{%=menu.url%}" menuId="{%=menu.id%}"
                     s-click="openMenuById('{%=menu.id%}')">
                    <div class="sidebar-title-inner">
                        <span class="sidebar-title-icon {%=menu.icon%}"></span>
                        <span class="sidebar-title-text">{%=menu.title%}</span>
                    </div>
                </div>
                {%}%}
            </div>
            {% }) %}
        </div>
    </div>
    <div class="main-right-panel">
        <ul class="window-tabs" id="mainTabContainer">

        </ul>
        <div class="main-window" id="mainWindow">
            <div class="window-container" id="windowContainer">

            </div>
        </div>
    </div>
</div>
<!--ajax操作提示-->
<div class="alert alert-warning ajax-active-tip " role="alert" id="ajaxActiveTip"></div>

<div class="main-bottom" id="mainBottom" s="window" ></div>

<ul id="mainTabContextmenu" s="contextmenu" s-contextmenu="{filter: MainTabContextmenu.filter}"
    class="s-ui-contextmenu">
    <li menuId="close" s-click="MainTabContextmenu.closeTarget()">
        <span>关闭</span>
    </li>
    <li class="s-ui-contextmenu-line"></li>
    <li menuId="clostOther" s-click="MainTabContextmenu.closeOthers()">
        <span>关闭其他</span>
    </li>
    <li menuId="closeAll" s-click="MainTabContextmenu.closeAll()">
        <span>关闭所有</span>
    </li>
    <li class="s-ui-contextmenu-line"></li>
    <li menuId="refresh" s-click="MainTabContextmenu.refreshTarget()">
        <span>刷新</span>
    </li>
</ul>

<ul id="mainContextmenu" s="contextmenu" class="s-ui-contextmenu">
    <li menuId="showSource" s-click="MainContextmenu.showSourceHtml(arguments[0])">
        <span>查看源码</span>
    </li>
    <li class="s-ui-contextmenu-line"></li>
    <li menuId="copyright" s-click="MainContextmenu.showCopyright()"><span>版权声明</span></li>
</ul>

<script type="text/javascript">

    //默认参数配置
    var loginProcessStatus = 0;
    var loginRetryCallbacks = [];
    Main = $.extend({
        menuUrl: null, //需要您来定义
        defaultTabIcon: "fa fa-file",
        defaultMenuIcon: "",
        topbarRightUrl: "html/topbar-right.html",
        topbarLeftUrl: "html/topbar-left.html",
        bottomUrl: null,
        loginPanel: "html/login-panel.html",
        tabActiveRefresh: true,
        init: function(){
            var that = this;
            $(window).on("popstate", function(e){
                var state = history.state;
                if(state !== undefined){
                    var tab = MainTab.findSingleTabByUrl(state.moduleUrl);
                    if(tab){
                        tab.active(false);
                    } else {
                        that.open($.Deferred(), state.moduleUrl, state.moduleArgs, false);
                    }
                } else {

                }
            });
        },
        handleAjaxError: function (e, errorTip, errorMsg, xhr) {
            if (xhr.status == 403) {
                e.stopPropagation();
                if(errorMsg == "LoginRequire"){ //需要登录
                    if (e.retryRequest) {
                        loginRetryCallbacks.push(e.retryRequest);
                    }
                    if (loginProcessStatus == 1) {
                        return;
                    }
                    //登陆超时
                    loginProcessStatus = 1;
                    S.popupOpen(Main.loginPanel).done(function (status) {
                        loginProcessStatus = 0;
                        if (status) {
                            $.each(loginRetryCallbacks, function (i, callback) {
                                callback();
                            })
                            loginRetryCallbacks = [];
                        }
                    })
                } else { //无权限操作
                    S.notice(errorMsg, "danger");
                }
                return;
            }
            S.notice($.trim(errorMsg), "danger");
        },
        historyListener: {
            onPush: function (tab) {
                history.pushState({moduleUrl:tab.data.url, moduleArgs: tab.data.args}, null , "#" + tab.data.url);
            },
            onGet: function () {
                var href = window.location.href;
                var hash;
                if (href.indexOf("#") != -1) {
                    hash = href.substring(href.indexOf("#") + 1);
                }
                return hash;
            }
        }
    }, Main || {});

    Main.init.call(S);

    //侧边栏子菜单打开合并
    S.N("#menuPanel").delegate(".sidebar-title", "click", function (e) {
        var node = $(e.currentTarget).parent();
        if (node.hasClass("menu-close")) {
            node.removeClass("menu-close");
        } else {
            var ul = node.find("> ul");
            ul.height(ul.height());
            setTimeout(function () {
                node.addClass("menu-close");
            }, 1);
        }
    });

    function activeSidebarMenuByUrl(url) {
        var node = $("*[menuurl='" + url + "']", S.N("#menuPanel"));
        activeSidebarMenu(node);
    }
    function activeSidebarMenu(node) {
        $("*[menuurl].active", S.N("#menuPanel")).removeClass("active");
        node && node.size() && node.addClass("active");
    }

    function openMenuById(id) {
        var menu = MenuPanel.getMenuById(id);
        var tabNode = $("*[menuurl='" + menu.url + "']", S.N("#mainTabContainer"));
        if (tabNode.size() > 0) {
            var tab = tabNode.data("tab");
            tab.active();
            if(Main.tabActiveRefresh){
                tab.tabWindows[0].smart.refresh();
            }
            return;
        }
        new MainTab(menu).add().active();
    }

    S.N("#mainTabContainer").sortable({axis: "x"});

    $("body").on("open", function (e, url) {
        if (/^menu:.+$/gi.test(url)) {
            openMenuById(url.substring(5));
        } else {
            if (url.indexOf("url:") == 0) url = url.substring(4);
            var nowUrl = e.smart.widget.window.location.href;
            if (!Smart.isEmpty(nowUrl)) {
                url = Smart.realPath(url, nowUrl);
            }
            openUrl(e.deferred, url, Smart.SLICE.call(arguments, 2));
        }
        e.stopPropagation();
    });

    var openUrl = S.open = function (deferred, url, args, pushStateFlag) {
        //在已经打开的选项卡中，根据url获取选项卡，判断其上面是否有single=true的属性，如果有，则直接把该选项卡打开，而不是打开新的页面
        if(pushStateFlag === undefined){
            pushStateFlag = true;
        }
        var tab = MainTab.findSingleTabByUrl(url);
        if (tab) {
            tab.active(pushStateFlag);
            if(Main.tabActiveRefresh){
                tab.tabWindows[0].smart.refresh();
            }
            return;
        }
        //根据当前控件的url处理 打开的url的真实路径。
        var data = {
            title: "加载中",
            type: "url",
            url: url,
            deferred: deferred,
            args: args
        };
        new MainTab(data).add().active(pushStateFlag);
    };

    //菜单面板
    var MenuPanel = {
        smart: S.S("#menuPanel"),
        menuMapping: {},
        loadMenu: function () {
            var menuUrl = Main.menuUrl;
            if (Smart.isEmpty(menuUrl)) {
                S.alert("请先定义menuUrl");
                return;
            }
            var that = this;
            S.get(menuUrl).done(function (menus) {
                that.menus = menus;
                var urlMapping = {};
                var needOpenMenus = [];
                $.each(menus, function (i, menu) {
                    urlMapping[menu.url] = menu;
                    menu.icon = menu.icon || Main.defaultMenuIcon;
                    that.menuMapping[menu.id] = menu;
                    if (menu.open) {
                        needOpenMenus.push(menu);
                    }
                    if (menu.children) {
                        $.each(menu.children, function (i, cm) {
                            that.menuMapping[cm.id] = cm;
                            if (cm.open) {
                                needOpenMenus.push(cm);
                            }
                        });
                    }
                });
                that.smart.data({menus: menus});
                var openMainTab;
                //如果根据hash要打开的页面的url和默认需要打开的有相同的，则不需要创建新的，直接将已经打开的置为active。
                var openedUrlMap = {};
                var hash = Main.historyListener.onGet();
                $.each(needOpenMenus, function (i, m) {
                    var _openMainTab;
                    if (m.url) {
                        _openMainTab = openedUrlMap[m.url] = new MainTab(m).add();
                    }
                    if (i == 0) {
                        openMainTab = _openMainTab;
                    }
                });
                if (hash) {
                    if (hash in openedUrlMap) {
                        openedUrlMap[hash].active();
                    } else if (hash in urlMapping) {
                        var menu = urlMapping[hash];
                        new MainTab(menu).add().active();
                    } else {
                        openUrl(null, hash, null);
                    }
                } else {
                    openMainTab && openMainTab.active();
                }
            });
            return this;
        },
        getMenuById: function (id) {
            return this.menuMapping[id];
        }
    };

    S.on("s-ready", function () {
        MenuPanel.loadMenu();
    });

    //主选项
    function MainTab(data) {
        this.data = data;
        this.tabWindows = [];
        var tabWindow = new TabWindow(this.data, this);
        this.bindTabWindowEvent(tabWindow);
        this.tabWindows.push(tabWindow);
        this.currentTabWindow = this.currentTabWindow || this.tabWindows[0];
    }

    MainTab.findSingleTabByUrl = function (url) {
        var tabNode = $("*[menuurl='" + url + "']", MainTab.container);
        if (tabNode.size() != 1) {
            return null;
        }
        return tabNode.data("tab").single ? tabNode.data("tab") : null;
    }

    MainTab.container = S.N("#mainTabContainer");
    MainTab.currentTab = null;
    MainTab.TabStack = {
        stack: [],
        pushTop: function (mainTab) {
            if (this.stack.length) {
                if (this.stack[this.stack.length - 1] == mainTab) {
                    return;
                }
            }
            this.stack = Smart.removeArrayElement(mainTab, this.stack);
            this.stack.push(mainTab);
        },
        getTop: function () {
            if (this.stack.length) {
                return this.stack[this.stack.length - 1];
            }
            return null;
        },
        remove: function (mainTab) {
            this.stack = Smart.removeArrayElement(mainTab, this.stack);
        }
    };
    MainTab.activeTop = function () {
        var topTab = MainTab.TabStack.getTop();
        topTab && !topTab.isTop() && topTab.active();
    };

    MainTab.closeMainTabs = function (mainTabs) {
        var deferred = $.Deferred();

        function closeMainTab(i) {
            if (i >= mainTabs.length) {
                return deferred.resolve();
            }
            mainTabs[i].close().done(function () {
                closeMainTab(i + 1);
            })
        }

        closeMainTab(0);
        return deferred;
    };

    MainTab.prototype = {
        add: function () {
            var data = this.data;
            this.node = $('<li menuurl="' + data.url + '"><a href="javascript:;"></a></li>');
            var a = $("a", this.node);
            this.titleNode = $("<span> " + data.title + "</span>");
            this.iconNode = $("<i class='" + (data.icon ? data.icon : Main.defaultTabIcon) + "'></i> ");
            a.append(this.iconNode);
            a.append(this.titleNode);
            this.node.attr("title", data.title);
            this.node.data("tab", this);
            this.bindEvent();
            MainTabContextmenu.bindTarget(this.node, this);
            MainTab.container.append(this.node);
            MainTab.TabStack.pushTop(this);
            return this;
        },
        _addCloseHandle: function () {
            var closeSpan = $("<div>×</div>");
            this.node.addClass("closeable").append(closeSpan);
            var that = this;
            this.closeHandle = closeSpan.click(function (e) {
                that.close();
                e.stopPropagation();
            });
        },
        _removeCloseHandle: function () {
            this.closeHandle.unbind().remove();
        },
        bindEvent: function () {
            this.node.click($.proxy(this.active, this));
            return this;
        },
        close: function () {
            var that = this;
            var deferred = $.Deferred();

            function closeTabWindow(i) {
                if (i >= that.tabWindows.length) {
                    return deferred.resolve();
                }
                var tabWindow = that.tabWindows[i];
                tabWindow.close().done(function () {
                    closeTabWindow(i + 1);
                });
            }

            closeTabWindow(0);
            return deferred;
        },
        refresh: function () {
            this.currentTabWindow.refresh();
        },
        active: function (pushStateFlag) {
            if (MainTab.currentTab == this) {
                return;
            }
            if(pushStateFlag === undefined){
                pushStateFlag = true;
            }
            var menuUrl = this.data.url;
            var sidebarMenuNode = $("*[menuurl='" + menuUrl + "']", S.N("#menuPanel"));
            if (sidebarMenuNode.size() > 0) {
                activeSidebarMenu(sidebarMenuNode);
            } else {
                activeSidebarMenu();
            }
            if (MainTab.currentTab) {
                MainTab.currentTab.fallow();
            }
            MainTab.currentTab = this;
            this.node.addClass("active");
            MainTab.TabStack.pushTop(this);
            this.showTabWindow(pushStateFlag);
            return this;
        },
        isTop: function(){
            return this.node.hasClass("active");
        },
        fallow: function () {
            this.node.removeClass("active");
            return this;
        },
        destroy: function () {
            this.node.remove();
            MainTab.TabStack.remove(this);
        },
        showTabWindow: function (pushStateFlag) {
            if (!this.currentTabWindow.made) {
                this.makeTabWindow(this.currentTabWindow);
            }
            this.currentTabWindow.show(pushStateFlag);
            return this;
        },
        makeTabWindow: function (tabWindow) {

            var that = this;
            if (Smart.isEmpty(this.data.children)) {
                tabWindow.smart.on("meta", function (e, key, value) {
                    if ($.type(key) == 'object') {
                        that.setMeta(key);
                    } else {
                        var meta = {};
                        meta[key] = value;
                        that.setMeta(meta);
                    }
                });
            }
            tabWindow.make().done(function (smart) {
                //如果该mainTab拥有子tab，则不设置meta
                if (Smart.isEmpty(that.data.children)) {
                    that.setMeta(smart.meta);
                }
            }).fail(function () {
                that._addCloseHandle();
            });
        },
        bindTabWindowEvent: function (tabWindow) {
            var that = this;
            var loadIcon = $('<loadi class="fa fa-circle-o-notch s-ui-spin"></loadi>');
            tabWindow.smart.on("close", function () {
                that.destroy();
                MainTab.activeTop();
            }).on("s-loading", function () {
                $("i", that.node).hide();
                $("loadi", that.node).remove();
                $("a", that.node).prepend(loadIcon);
            }).on("s-ready", function () {
                loadIcon.remove();
                $("i", that.node).show();
            });
        },
        setMeta: function (meta) {
            var that = this;
            if (meta.single === "" || meta.single === true || meta.single == "true" || meta.single == undefined) {
                meta.single = true;
            } else {
                meta.single = false;
            }
            $.each(meta || {}, function (key, value) {
                switch (key) {
                    case "title":
                        that.titleNode.html(" " + value);
                        that.node.attr("title", value);
                        break;
                    case "icon" :
                        that.iconNode.attr("class", "").addClass(value);
                        break;
                    case "description":
                        that.node.attr("title", value);
                        break;
                    case "single":
                        that.node.attr("single", value);
                        that.single = value;
                        break;
                }
            });
            if (meta.closeable === "true" || meta.closeable == undefined
                    || meta.closeable == "" || meta.closeable === true) {
                this._addCloseHandle();
            } else {
                this.node.attr("closeable", "false");
            }
        }
    };

    var MainTabContextmenu = {
        smart: S.S("#mainTabContextmenu"),
        bindTarget: function (node, mainTab) {
            node.data("mainTab", mainTab);
            this.smart.bindTarget(node);
        },
        filter: function (menuId) {
            if (menuId == "close") {
                var target = Smart.UI.contextmenu.target;
                return !(target.node.attr("closeable") == 'false');
            }
        },
        closeTarget: function () {
            var target = Smart.UI.contextmenu.target;
            var mainTab = target.node.data("mainTab");
            mainTab.close();
            MainTab.activeTop();
        },
        closeOthers: function () {
            var target = Smart.UI.contextmenu.target;
            var others = target.node.siblings();
            this.closeNodes(others);
        },
        closeAll: function () {
            var tabs = MainTab.container.children();
            this.closeNodes(tabs);
        },
        closeNodes: function (nodes) {
            var mainTabs = [];
            $.each(nodes, function () {
                if ($(this).attr("closeable") == 'false')
                    return;
                var mainTab = $(this).data("mainTab");
                mainTabs.push(mainTab);
            });
            MainTab.closeMainTabs(mainTabs).done(function () {
                MainTab.activeTop();
            });
        },
        refreshTarget: function () {
            var target = Smart.UI.contextmenu.target;
            var mainTab = target.node.data("mainTab");
            mainTab.refresh();
        }
    };

    var MainContextmenu = {
        smart: S.S("#mainContextmenu"),
        bindTarget: function (node, mainTab) {
            node.data("mainTab", mainTab);
            this.smart.bindTarget(node);
        },
        showCopyright: function () {
            S.alert("iSmart JS 版权所有，QQ群：51729123");
        },
        showSourceHtml: function () {
            var node = Smart.UI.contextmenu.node;
            var windowSmart = Smart.of(node).closest('window');
            if (windowSmart == null) return;
            var menu = {
                url: 'source-view.html',
                args: [{url: windowSmart.widget.window.location.href}]
            };
            new MainTab(menu).add().active();
        }
    };

    this.on("s-ready", function () {
        //MainContextmenu.bindTarget($("body"));
    });

    function showTabWindowById(id) {
        var tabWindow = TabWindow.mapping[id];
        !tabWindow.made && tabWindow.make();
        tabWindow.show();
    }

    function TabWindow(data, mainTab) {
        this.data = data
        this.made = false;
        this.mainTab = mainTab;
        this.id = TabWindow.getToken();
        TabWindow.mapping[this.id] = this;
        this.node = $("<div s='window' />").html("正在加载……");
        this.smart = Smart.of(this.node);
    }
    TabWindow.container = S.N("#windowContainer");
    TabWindow.currentTabWindow = null;
    TabWindow.token = 0;
    TabWindow.getToken = function () {
        return "_tab_window_" + (TabWindow.token++ );
    };
    TabWindow.mapping = {};
    TabWindow.prototype = {
        show: function (pushStateFlag) {
            if (TabWindow.currentTabWindow) {
                TabWindow.currentTabWindow.hide();
            }
            TabWindow.currentTabWindow = this;
            this.mainTab.currentTabWindow = this;
            this.node.fadeIn();
            if (this.data.url && pushStateFlag){
                Main.historyListener.onPush(this.mainTab);
            }
        },
        hide: function () {
            this.node.hide();
        },
        make: function () {
            this.made = true;
            this.smart.render();
            TabWindow.container.append(this.node);
            if (!this.data.url) return $.Deferred().resolve(this.smart);
            return this.smart.load.apply(this.smart, [this.data.url].concat(this.data.args));
        },
        close: function () {
            if (!this.made) {
                this.smart.trigger("close");//因为MainTab的关闭是监听的该smart的close事件，如果没有made，则在这里直接trigger一个close事件
                return $.Deferred().resolve();
            }
            var that = this;
            return this.smart.closeWithConfirm().done(function () {
                delete TabWindow.mapping[that.id];
                delete that.mainTab.currentTabWindow;
                delete that.mainTab;
            });
        },
        refresh: function () {
            this.smart.refresh().fail(function () {

            });
        }
    };

    //处理ajax tip
    var ajaxActiveTip = S.N("#ajaxActiveTip");
    var closeTimeout;
    function showAjaxActiveTip(msg, level) {
        var removeClass;
        var addClass;
        if (level == "warning") {
            removeClass = "alert-success alert-danger";
            addClass = "alert-warning";
        } else if (level == "success") {
            removeClass = "alert-warning alert-danger";
            addClass = "alert-success";
        } else {
            removeClass = "alert-warning alert-success";
            addClass = "alert-danger";
        }
        ajaxActiveTip.removeClass(removeClass).addClass(addClass).css('z-index', Smart.UI.zIndex()).show().html(msg);
    }
    function hideAjaxActiveTip() {
        if (closeTimeout) {
            clearTimeout(closeTimeout);
        }
        closeTimeout = setTimeout(function () {
            ajaxActiveTip.fadeOut(200);
            closeTimeout = 0;
        }, 1500);
    }
    $("body").on("smart-ajaxStart", function (e, tip) {
        showAjaxActiveTip(tip, "warning");
    }).on("smart-ajaxSuccess", function (e, tip) {
        showAjaxActiveTip(tip, "success");
        hideAjaxActiveTip();
    }).on("smart-ajaxError", function (e, errorTip, msg) {
        Main.handleAjaxError ? Main.handleAjaxError.apply(S, Array.prototype.slice.call(arguments))
                : (S.alert($.trim(msg), "error"));
        showAjaxActiveTip(errorTip, "error");
        hideAjaxActiveTip();
    });
    //处理bottom的url问题，mainWindow的底部位置
    if(Main.bottomUrl){
        S.on("s-ready", function(){
            S.S("#mainBottom").load(Main.bottomUrl).done(function(){
                var node = S.N("#mainBottom");
                S.N("#mainView").css("bottom", node.height());
            });
        });
    } else {
        S.N("#mainBottom").remove();
    }
</script>